package org.minuframework.core.io;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.nio.channels.FileChannel;

public class IOUtils {
    
    // ------------------------------------------------------------------------
    // ************************************************************************
    // constants
    
    public static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
    
    // ************************************************************************
    // public methods
    
    // ------------------------------------------------------------------------
    
    public static long copy(final InputStream in, final OutputStream out) throws IOException {
        long count = copyLarge(in, out);
        if (count > Long.MAX_VALUE) { return -1; }
        return count;
    }
    
    private static long copyLarge(final InputStream in, final OutputStream out) throws IOException {
        return copyLarge(in, out, new byte[DEFAULT_BUFFER_SIZE]);
    }
    
    private static long copyLarge(final InputStream in, final OutputStream out, final byte[] buffer) throws IOException {
        long count = 0;
        int len = 0;
        while ((len = in.read(buffer)) > 0) {
            out.write(buffer, 0, len);
            count += len;
        }
        return count;
    }
    
    // ------------------------------------------------------------------------
    
    public static long write(final InputStream in, final OutputStream out) throws IOException {
        long count = writeLarge(in, out);
        if (count > Long.MAX_VALUE) { return -1; }
        return count;
    }
    
    private static long writeLarge(final InputStream in, final OutputStream out) throws IOException {
        return writeLarge(in, out, new byte[DEFAULT_BUFFER_SIZE]);
    }
    
    private static long writeLarge(final InputStream in, final OutputStream out, final byte[] buffer) throws IOException {
        int count = 0;
        int len = 0;
        while ((len = in.read(buffer)) != -1) {
            out.write(buffer, 0, len);
            count += len;
        }
        out.flush();
        return count;
    }
    
    public static void write(final FileChannel in, final FileChannel out) throws IOException {
        in.transferTo(0, in.size(), out);
    }
    
    // ------------------------------------------------------------------------
    
    public static void close(final InputStream in) {
        try {
            if (in != null) {
                in.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static void close(final OutputStream out) {
        try {
            if (out != null) {
                out.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static void close(final Closeable closeable) {
        try {
            if (closeable != null) {
                closeable.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static void close(final Reader reader) {
        try {
            if (reader != null) {
                reader.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static void close(final Writer writer) {
        try {
            if (writer != null) {
                writer.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
}
